﻿using System;
using System.Collections;
using System.Net;
using System.Text.RegularExpressions;

namespace SimpleWebCrawler
{
    public class Crawler
    {
        private Hashtable urls = new Hashtable();
        private int count = 0;
        public Action<string, bool> UpdateResultList;

        public Crawler(string startUrl)
        {
            if (Uri.TryCreate(startUrl, UriKind.Absolute, out Uri result))
            {
                urls.Add(result.AbsoluteUri, false);
            }
            else
            {
                throw new Exception("Invalid URL");
            }
        }

        public void Start()
        {
            foreach (DictionaryEntry entry in urls)
            {
                if ((bool)entry.Value) continue;
                string currentUrl = (string)entry.Key;
                urls[currentUrl] = true;
                string html = DownLoad(currentUrl);
                if (html != "") Parse(html, currentUrl);
                if (++count > 10) break;  // Limit the number of pages to crawl
            }
        }

        private string DownLoad(string url)
        {
            try
            {
                WebClient webClient = new WebClient();
                webClient.Encoding = System.Text.Encoding.UTF8;
                string html = webClient.DownloadString(url);
                UpdateResultList?.Invoke(url, false);
                return html;
            }
            catch
            {
                UpdateResultList?.Invoke(url, true);
                return "";
            }
        }

        private void Parse(string html, string baseUrl)
        {
            var baseUri = new Uri(baseUrl);
            var matches = new Regex(@"(href|HREF)=""([^""]*)""").Matches(html);
            foreach (Match match in matches)
            {
                string url = match.Groups[2].Value;
                if (!url.StartsWith("http://") && !url.StartsWith("https://"))
                {
                    url = new Uri(baseUri, url).ToString();
                }
                if (!urls.Contains(url))
                {
                    urls.Add(url, false);
                }
            }
        }
    }
}
